<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数作用域和闭包</title>
  </head>
  <body></body>
  <script>
    /**
     * 函数作用域（MDN）
     * 在函数内定义的变量不能在函数之外的任何地方访问，因为变量仅仅在该函数的域的内部有定义。
     * 相对应的，一个函数可以访问定义在其范围内的任何变量和函数。
     * 换言之，定义在全局域中的函数可以访问所有定义在全局域中的变量。
     * 在另一个函数中定义的函数也可以访问在其父函数中定义的所有变量和父函数有权访问的任何其他变量。
     *
     * 闭包（MDN）
     * 一个函数和对其周围状态（lexical environment，词法环境）的引用捆绑在一起（或者说函数被引用包围），这样的组合就是闭包（closure）。
     * 也就是说，闭包让你可以在一个内层函数中访问到其外层函数的作用域。
     * 在 JavaScript 中，每当创建一个函数，闭包就会在函数创建的同时被创建出来。
     *
     * 函数作用域链
     * 函数内变量的值通过作用域链进行查找赋值。首先在本作用域进行查找，若没有则往声明当前函数的父级作用域进行查找
     */

    // 函数作为返回值
    let a = 200;
    function fn() {
      let a = 100;
      return function () {
        console.log(a);
      };
    }
    let fo = fn();
    fo();
    // 输出结果为：100 => fo 函数声明位置在 fn 作用域 内部

    // 函数作为参数
    let b = 200;
    function bar(fn) {
      let b = 100;
      fn();
    }
    function baz() {
      console.log(b);
    }
    bar(baz);
    // 输出结果为：200 => baz 函数声明位置在 全局作用域 内部
  </script>
</html>
